<template>
  <div class="t-tree">
    <van-checkbox-group v-model="checked">
      <ul>
        <item
          v-for="(item,index) in list" :key="index"  
          :item="item" 
          :label-name="labelName" 
          :value-name="valueName" 
          :checkbox="checkbox"
        />
      </ul>
    </van-checkbox-group>
     <div class="btns">
      <van-button 
        type="primary"
        size="small"
        block
        color="var(--van-primary-color)"
        @click="confirm">
        确认
      </van-button>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent,reactive,toRefs,watch,provide,nextTick ,readonly} from 'vue'
import {treeTransObject} from '@/utils'
import item from "./item.vue"
export default defineComponent({
  name: 'tTree',
  emits: ['select'],
  props: {
    labelName:{
      type: String,
      default: 'label'
    },
    valueName:{
      type: String,
      default: 'value'
    },
    checkbox:{
      type: Boolean,
      default: false
    },
    open:{
      type: Boolean,
      default: false
    },
    list:Array,
    defaultValue: String,
  },
  setup (props,{emit}) {
    const data = reactive({})
    const rootObj = reactive(treeTransObject(props.list,{id:props.valueName}));
    const checked = reactive<Array<any>>([])
    const checkedFather = reactive<Array<any>>([])
    const deleteFatherId = function(id){
      let oldCheckedFather = JSON.parse(JSON.stringify(checkedFather));
      let allList:Array<any> = [];
      checkedFather.splice(0);
      const loopFun = function(id){
        if(rootObj[id] && rootObj[id]['parentId']){
          allList.push(rootObj[id]['parentId']);
          loopFun(rootObj[id]['parentId']);
        }
      }
      loopFun(id);
      checkedFather.push(...oldCheckedFather.filter(treeId=>{
        return allList.indexOf(treeId) == -1;
      }))
    }
    const addFatherId = function(id){
      let allList:Array<any> = [];
      const loopFun = function(id){
        if(rootObj[id] && rootObj[id]['parentId']){
          let isAll = true;
          Object.values(rootObj).forEach(item=>{
            if(item['parentId']==rootObj[id]['parentId'] && checked.indexOf(item[props.valueName]) == -1 && checkedFather.indexOf(item[props.valueName]) == -1){
              isAll = false;
            }
          });
          if(isAll){
            checkedFather.push(rootObj[id]['parentId']);
            loopFun(rootObj[id]['parentId']);
          }
        }
      }
      loopFun(id);
      checkedFather.push(...allList)
    }
    const treeFun = function(tree,state){
      if(tree.children){
        if(state){
          checkedFather.push(tree[props.valueName])
        }else{
          let oldCheckedFather = JSON.parse(JSON.stringify(checkedFather));
          checkedFather.splice(0);
          checkedFather.push(...oldCheckedFather.filter(treeId=>{
            return treeId != tree[props.valueName]
          }))
        }
        tree.children.forEach(treeItem => {
          treeFun(treeItem,state)
        });
      }else{
        if(state){
          checked.indexOf(tree[props.valueName]) == -1 && checked.push(tree[props.valueName])
        }else{
          let oldChecked = JSON.parse(JSON.stringify(checked));
          checked.splice(0);
          checked.push(...oldChecked.filter(treeId=>{
            return treeId != tree[props.valueName]
          }))
        }
      }
    }
    provide('checked',checked);
    provide('checkedFather',checkedFather);
    provide('rootObj',readonly(rootObj));
    provide('deleteFatherId',deleteFatherId);
    provide('addFatherId',addFatherId);
    provide('treeFun',treeFun);

    const updateSelect = function(value,state=true){
      if(!value)return;
      checked.splice(0);
      checkedFather.splice(0);
      value.split(',').forEach(id => {
        checked.push(id)
        if(props.checkbox){//如果是多选
          addFatherId(id)
        }
      });
      if(props.list && props.list.length >0){
        emit('select',checked.map(item=>rootObj[item]).filter(item=>item),state)
      }
    }
    watch(()=>props.defaultValue,(nowData:any,prev)=>{
      updateSelect(nowData);
    });
    watch(()=>props.list,(nowData:any,prev)=>{
      let nowObj = treeTransObject(nowData,{id:props.valueName});
      for(let key in rootObj){
          delete rootObj[key];
      }
      Object.keys(nowObj).forEach(key=>{
        rootObj[key] = nowObj[key]
      }) 
      updateSelect(props.defaultValue,false)
    });
    nextTick(()=>{
      updateSelect(props.defaultValue);
    })
    return {
      ...toRefs(data),
      checkedFather,
      checked,
      rootObj,
      confirm(){
        emit('select',checked.map(item=>rootObj[item]))
      },
    }
  },
  components:{item}
})
</script>

<style lang="scss">
.t-tree{
  position: relative;
  padding: 40px 10px;
  font-size: 14px;
  line-height: 25px;
  &>.van-checkbox-group{
    max-height: calc(90vh - 100px);
    overflow: auto;
  }
  .checkboxLabel{
    display: inline-block;
    vertical-align: middle;
    margin: 0 5px 0 4px;
  }
  .btns{
    position: absolute;
    bottom: 5px;
    left: 16px;
    right: 16px;
  }
}
</style>